package br.com.sebrae.pr.sgp.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

import org.apache.commons.lang3.StringUtils;

import br.com.sebrae.pr.sgp.dao.UsuarioDAO;
import br.com.sebrae.pr.sgp.dao.base.BaseDao;
import br.com.sebrae.pr.sgp.entities.Usuario;
import br.com.sebrae.pr.sgp.util.persistence.IConverter;
import br.com.sebrae.pr.sgp.util.persistence.ItemResultset;
import br.com.sebrae.pr.sgp.util.persistence.params.InParam;
import br.com.sebrae.pr.sgp.util.persistence.params.ParamType;

import com.google.common.base.Preconditions;

@Stateless
@TransactionManagement(value = TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public class UsuarioDaoImpl extends BaseDao implements UsuarioDAO {

    @Override
    public Usuario pesquisarPorId(final long id) {
        final Usuario filtro = new Usuario();
        filtro.setId(id);
        final List<Usuario> ret = pesquisar(filtro);
        if (ret.iterator().hasNext()) {
            return ret.iterator().next();
        }
        return null;
    }

    @Override
    public Usuario pesquisarPorLogin(final String nmeLogin) {
        final Usuario filtro = new Usuario();
        filtro.setNomeUsuario(nmeLogin);
        final List<Usuario> ret = pesquisar(filtro);
        if (ret.iterator().hasNext()) {
            return ret.iterator().next();
        }
        return null;
    }

    @Override
    public Usuario pesquisarPorLoginSenha(final String nmeLogin, final String desSenhaMd5) {
        final Usuario filtro = new Usuario();
        filtro.setNomeUsuario(nmeLogin);
        filtro.setSenha(desSenhaMd5);
        final List<Usuario> ret = pesquisar(filtro);
        if (ret.iterator().hasNext()) {
            return ret.iterator().next();
        }
        return null;
    }

    @Override
    public Usuario pesquisarPorNmeUsuarioSvn(final String nmeUsuarioSvn) {
        final Usuario filtro = new Usuario();
        filtro.setNomeUsuario(nmeUsuarioSvn);
        final List<Usuario> ret = pesquisar(filtro);
        if (ret.iterator().hasNext()) {
            return ret.iterator().next();
        }
        return null;
    }

    @Override
    public List<Usuario> efetuarPesquisa(final Usuario usuario) {
        return pesquisar(usuario, true);
    }




    /**
     * Pesquisa os usuários utilizando os campos do {@link Usuario} parâmetro como filtros. Não utiliza like mas =
     * 
     * @see UsuarioDaoImpl#pesquisar(Usuario, boolean)
     * 
     * @param filtro
     * @return
     */
    private List<Usuario> pesquisar(final Usuario filtro) {
        return pesquisar(filtro, false);
    }

    /**
     * Pesquisa os usuários utilizando os campos do {@link Usuario} parâmetro como filtros. Utiliza LIKE se o parametro paraPesquisa = true
     * 
     * @param filtro
     * @param paraPesquisa
     * @return
     */
    private List<Usuario> pesquisar(final Usuario filtro, final boolean paraPesquisa) {
        final List<InParam> params = new ArrayList<InParam>();

        final StringBuffer sql = new StringBuffer();
        sql.append("SELECT id, \n");
        sql.append("       nome_usuario \n");
        sql.append("  FROM usuario \n");
        sql.append(" WHERE 1 = 1 \n");
        if (filtro != null) {
            if (paraPesquisa) {
                if (StringUtils.isNotBlank(filtro.getNomeUsuario())) {
                    sql.append("   AND (UPPER(usuario.a1083_login) LIKE(?) OR UPPER(usuario.a1083_usr_svn) LIKE(?))\n");
                    params.add(new InParam(params.size() + 1, "%" + filtro.getNomeUsuario().toUpperCase() + "%", ParamType.VARCHAR));
                    params.add(new InParam(params.size() + 1, "%" + filtro.getNomeUsuario().toUpperCase() + "%", ParamType.VARCHAR));
                }
                if (StringUtils.isNotBlank(filtro.getNomeUsuario())) {
                    sql.append("   AND UPPER(ag.a0015_nm_agente) LIKE(?) \n");
                    params.add(new InParam(params.size() + 1, "%" + filtro.getNomeUsuario().toUpperCase() + "%", ParamType.VARCHAR));
                }

            } else {
                if (StringUtils.isNotBlank(filtro.getNomeUsuario())) {
                    sql.append("   AND nome_usuario = ? \n");
                    params.add(new InParam(params.size() + 1, filtro.getNomeUsuario(), ParamType.VARCHAR));
                }
                if (StringUtils.isNotBlank(filtro.getSenha())) {
                    sql.append("   AND senha = ? \n");
                    params.add(new InParam(params.size() + 1, filtro.getSenha(), ParamType.VARCHAR));
                }
            }
        }
        return executarQuery(sql, params, new IConverter<Usuario>() {

            @Override
            public Usuario convert(final ItemResultset reg) {
                final Usuario ret = new Usuario();
                ret.setId(reg.getLong("id"));
                ret.setNomeUsuario(reg.getString("nome_usuario"));
                return ret;
            }
        });
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public Usuario salvarOuAtualizar(final Usuario usuario) {
        Preconditions.checkNotNull(usuario, "Usuário é obrigatório e deve ser informado!");
        Preconditions.checkNotNull(usuario.getUsuarioLogado().getId(), "ID do usuário logado é obrigatório e deve ser informado!");
        final List<InParam> params = new ArrayList<InParam>();
        if (inclusao(usuario)) {
            throw new IllegalArgumentException("Inclusão de usuários não é contemplada no sistema!");

        } else {
            final StringBuffer sql = new StringBuffer();
            sql.append("UPDATE master.tb1083_vc_user \n");
            sql.append("   SET a1083_usr_svn = ?, \n");
            sql.append("       a1083_email = ?, \n");
            sql.append("       a1083_passwd_md5 = ?, \n");
            sql.append("       a1083_ind_admin = ?, \n");
            sql.append("       a1083_ind_desenv = ?, \n");
            sql.append("       a1083_ind_integrador = ?, \n");
            sql.append("       a1083_ind_aprovador = ?, \n");
            sql.append("       a1083_ind_testador = ?, \n");
            sql.append("       a1083_ind_dba = ?, \n");
            sql.append("       a1083_ind_po = ?, \n");
            sql.append("       a1083_dt_atz = ?, \n");
            sql.append("       a0015_cod_agente_atz = ? \n");
            sql.append(" WHERE a0015_cod_agente = ? \n");

//            params.add(new InParam(params.size() + 1, usuario.getNmeUsuarioSvn(), ParamType.VARCHAR));
//            params.add(new InParam(params.size() + 1, usuario.getDesEmail(), ParamType.VARCHAR));
//            params.add(new InParam(params.size() + 1, usuario.getDesSenha(), ParamType.VARCHAR));
//            params.add(new InParam(params.size() + 1, usuario.getAdmin(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, usuario.getDesenvolvedor(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, usuario.getIntegrador(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, usuario.getAprovador(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, usuario.getTestador(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, usuario.getDba(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, usuario.getPo(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, new Date(), ParamType.TIMESTAMP));
//            params.add(new InParam(params.size() + 1, usuario.getUsuarioLogado().getId(), ParamType.NUMERIC));
//            params.add(new InParam(params.size() + 1, usuario.getId(), ParamType.NUMERIC));

            executarUpdate(sql, params);

        }
        return usuario;
    }
}
